#include"HiKernel/HiGBRenderer.h"
#include "HiModules/mHiDummy/LM_Anim.h"

#include <windows.h>
#include <NiMain.h>
#include <NiAnimation.h>
#include <NiParticle.h>
#include <NiApplication.h>
#include <NiCollision.h>


#include <NiDebug.h>
//
#ifndef _LIB
#define _LIB
#endif //#ifndef _LIB
#include <NSBShaderLib.h>
#include <NSFParserLib.h>

#if defined(WIN32)
#pragma comment(lib, "NiBinaryShaderLibDX9.lib")
#pragma comment(lib, "NiD3D10BinaryShaderLibD3D10.lib")
#pragma comment(lib, "NSBShaderLibDX9.lib")
#pragma comment(lib, "NSFParserLibDX9.lib")
#elif defined(_XENON)
#pragma comment(lib, "NiBinaryShaderLib.lib")
#pragma comment(lib, "NSBShaderLib.lib")
#pragma comment(lib, "NSFParserLib.lib")
#elif defined (_PS3)
#else
#error "target platform not defined"
#endif  // #if defined(WIN32)
//

#include <NiDX9Renderer.h>
#pragma comment(lib, "NiDX9Renderer.lib")
#pragma comment(lib, "dxguid.lib")

#include <NiD3D10Renderer.h>
#pragma comment(lib, "NiD3D10Renderer.lib")

#pragma comment(lib, "NiInput.lib")
#include <NiInput.h>
#include <NiInputSystem.h>



NiDX9Renderer* g_dx9renderer= NULL;

HiGBRenderer::HiGBRenderer(): HiRenderer(Gamebryo)
{
	NiInit();

	m_kGroundPick.SetPickType(NiPick::FIND_FIRST);
	m_kGroundPick.SetSortType(NiPick::NO_SORT);
	m_kGroundPick.SetIntersectType(NiPick::TRIANGLE_INTERSECT);
	// Assumes model coordinates have already been transformed to world
	m_kGroundPick.SetCoordinateType(NiPick::MODEL_COORDINATES);
	m_kGroundPick.SetFrontOnly(false);
	m_kGroundPick.SetObserveAppCullFlag(true);
	m_kGroundPick.SetReturnTexture(false);
	m_kGroundPick.SetReturnNormal(false);
	m_kGroundPick.SetReturnSmoothNormal(false);
	m_kGroundPick.SetReturnColor(false);
}

HiGBRenderer::~HiGBRenderer()
{
	Terminate();
}


bool HiGBRenderer::Initalize(HWND hWnd, HINSTANCE hInst)
{
	if (!CreateRenderer(hWnd))
        return false;

    if (!CreateCamera())
        return false;

    /*if (!CreateInputSystem())
        return false;*/

	if (!CreateScene())
    {
        //NIMETRICS_APPLICATION_ENDTIMER(kTimer);
        return false;
    }
    /*NIMETRICS_APPLICATION_ENDTIMER(kTimer);

    if (m_bUseFrameSystem && !CreateFrame())
        return false;*/

    if (m_spScene)
    {
        m_spScene->Update(0.0f);
        m_spScene->UpdateProperties();
        m_spScene->UpdateEffects();
    }

    if (m_spCamera)
    {
        m_spCamera->Update(0.0f);
    }

	CreateInputSystem(hWnd,hInst);

	return true;
}

bool HiGBRenderer::CreateRenderer(HWND hWnd)
{
	m_hWnd = hWnd;

	
	NiImageConverter::SetImageConverter(NiNew NiDevImageConverter);
	NiTexture::SetMipmapByDefault(true);
	NiSourceTexture::SetUseMipmapping(true);

	// Setup the material shader generation folder prior to creating the 
	// renderer.
	NiMaterial::SetDefaultWorkingDirectory("./Shaders/Generated");

	// create a renderer
	m_spRenderer = NiDX9Renderer::Create(0, 0, 0, m_hWnd, NULL);

	g_dx9renderer =  (NiDX9Renderer*)NiRenderer::GetRenderer();


	bool bSuccess = (m_spRenderer != NULL);

	if (!bSuccess || !m_spRenderer)
	{
		OutputDebugString("Direct3D renderer creation error: ");
		OutputDebugString(NiRenderer::GetLastErrorString());
		OutputDebugString("\n");

		NiMessageBox::DisplayMessage("Unable to create a DX9 Renderer.\n", "DX9 Renderer Creation Failed");

		return false;
	}

	m_spRenderer->SetBackgroundColor(NiColor(0.5f, 0.5f, 0.5f));


   /* const char* pcWorkingDir = ConvertMediaFilename("Shaders\\Generated");
    NiMaterial::SetDefaultWorkingDirectory(pcWorkingDir);

    NiWindowRef pWnd;
    if (m_bFullscreen)
        pWnd = m_pkAppWindow->GetWindowReference();
    else
        pWnd = m_pkAppWindow->GetRenderWindowReference();

    char acErrorStr[512];

    if (m_bD3D10Renderer)
    {
        m_spRenderer = NiD3D10Select::CreateRenderer(
            m_pkAppWindow->GetWindowReference(), m_bRendererDialog,
            m_pkAppWindow->GetWidth(), m_pkAppWindow->GetHeight(),
            m_bMultiThread, m_bRefRast, m_bFullscreen);
    }
    else
    {
        m_spRenderer = NiDX9Select::CreateRenderer(
            m_pkAppWindow->GetWindowReference(), 
            m_pkAppWindow->GetRenderWindowReference(), m_bRendererDialog, 
            m_uiBitDepth, m_pkAppWindow->GetWidth(), 
            m_pkAppWindow->GetHeight(), m_bStencil,
            m_bMultiThread, m_bRefRast, m_bSWVertex, m_bNVPerfHUD,
            m_bFullscreen);
    }

    if (m_spRenderer == NULL)
    {
        if (m_bD3D10Renderer)
        {
            NiStrcpy(acErrorStr, 512, "D3D10 Renderer Creation Failed");
            NiMessageBox::DisplayMessage("Unable to create a D3D10 Renderer.\n"
                "This symptom may indicate you are not running on a "
                "D3D10-capable graphics card.\n",
                "D3D10 Renderer Creation Failed");
        }
        else
        {
            NiStrcpy(acErrorStr, 512, "DX9 Renderer Creation Failed");
            NiMessageBox::DisplayMessage(
                "Unable to create a DX9 Renderer.\n",
                "DX9 Renderer Creation Failed");
        }

        return false;
    }
    else
    {
        m_spRenderer->SetBackgroundColor(NiColor(0.5f, 0.5f, 0.5f));
    }*/

    return true;
}

bool HiGBRenderer::CreateCamera()
{
    m_spCamera = NiNew NiCamera;
    NIASSERT(m_spCamera);

    float fAspectRatio = 1.0f;
    if (m_spRenderer)
    {
        Ni2DBuffer* pkBackbuffer = m_spRenderer->GetDefaultBackBuffer();
        fAspectRatio = (float)pkBackbuffer->GetWidth() / 
            (float)pkBackbuffer->GetHeight();
    }
    else
    {
      /*  fAspectRatio = (float)m_pkAppWindow->GetWidth() / 
            (float)m_pkAppWindow->GetHeight();*/
    }

    // Setup the camera frustum and viewport
    float fVerticalFieldOfViewDegrees = 20.0f;
    float fVerticalFieldOfViewRad =
        NI_PI / 180.0f * fVerticalFieldOfViewDegrees;
    float fViewPlaneHalfHeight = tanf(fVerticalFieldOfViewRad * 0.5f);
    float fViewPlaneHalfWidth = fViewPlaneHalfHeight * fAspectRatio;

    NiFrustum kFrustum = NiFrustum(
        -fViewPlaneHalfWidth, fViewPlaneHalfWidth, 
        fViewPlaneHalfHeight, -fViewPlaneHalfHeight,
        1.0f, 1000.0f);
    NiRect<float> kPort(0.0f, 1.0f, 1.0f, 0.0f);
    m_spCamera->SetViewFrustum(kFrustum);
    m_spCamera->SetViewPort(kPort);

    return true;
}

bool HiGBRenderer::CreateScene()
{
    m_spScene = NiNew NiNode;
    return true;
}

//bool HiGBRenderer::Create()
//{

//	CreateShaderSystem();


	//// create a scene
	//NiStream kStream;
	//bool bLoaded = kStream.Load("TheClockAndTheOcularis.nif");
	//NIASSERT(bLoaded);
	//m_spScene = NiDynamicCast(NiNode, kStream.GetObjectAt(0));
	//NIASSERT(m_spScene != NULL);
	//m_spCamera = NiDynamicCast(NiCamera, 
	//	kStream.GetObjectAt(1));
	//NIASSERT(m_spCamera != NULL);
	//kStream.RemoveAllObjects();

	//m_gs_spWireframe = NiNew NiWireframeProperty;
	//m_spScene->AttachProperty(m_gs_spWireframe);

	////RecursiveMunge(spScene);

	//// connect the parts and do initial update
	//m_spScene->Update(0.0f);
	//m_spScene->UpdateProperties();
	//m_spScene->UpdateEffects();
	//m_spCamera->Update(0.0f);

	//// All other smart pointers declared in this scope 
	//// (spRenderer, spScene, spCamera) will be deleted 
	// when the current scope ends
//	return true;
//}


void HiGBRenderer::BeginScene()
{
//	m_spScene->Update(NiGetCurrentTimeInSec());

//	m_spActorManager->Update(NiGetCurrentTimeInSec());


/*
	const unsigned int uiScreenWidth = m_spRenderer->
       GetDefaultRenderTargetGroup()->GetWidth(0);
   const unsigned int uiScreenHeight = m_spRenderer->
       GetDefaultRenderTargetGroup()->GetHeight(0);

#if defined(_PS3) || defined(_XENON)    
   const float fDesiredAspect = 1280.0/720.0;
#else
   const float fDesiredAspect = 4.0f/3.0f;
#endif

	float fAspect = (float)uiScreenWidth/(float)uiScreenHeight;
   if (NiAbs(fAspect - fDesiredAspect) > 0.01f)
   {
       // bad aspect ratio
       //WorldManager::Log("MetalWars: Splash aspect incorrect.\n");
   }

   NiScreenElements* pkSplash = NiNew NiScreenElements(
       NiNew NiScreenElementsData(false, false, 1));

   // We know that the polygon handle is zero and will use it directly in
   // the vertex and texture coordinate assignments.
   pkSplash->Insert(4);
   pkSplash->SetRectangle(0, 0.0f, 0.0f, 1.0f, 1.0f);
   pkSplash->UpdateBound();

   // We assume the splash screen is already the correct aspect ratio, and
   // can thus render the entire texture
   pkSplash->SetTextures(0, 0, 0.0f, 0.0f, 1.0f, 1.0f);

   // use a texture
   NiTexturingProperty* pkTex = NiNew NiTexturingProperty(
       "Splash.dds");
   pkTex->SetBaseClampMode(NiTexturingProperty::CLAMP_S_CLAMP_T);
   pkTex->SetApplyMode(NiTexturingProperty::APPLY_REPLACE);
   pkSplash->AttachProperty(pkTex);

   // no alpha blending
   NiAlphaProperty* pkAlpha = NiNew NiAlphaProperty;
   pkAlpha->SetAlphaBlending(false);
   pkSplash->AttachProperty(pkAlpha);

   pkSplash->UpdateProperties();
   pkSplash->Update(0.0f);

*/
	


	NiVisibleArray kVisible(32, 32);
    NiCullingProcess kCuller(&kVisible);
//	// Render frame
	m_spRenderer->BeginFrame();
	m_spRenderer->BeginUsingDefaultRenderTargetGroup(
		NiRenderer::CLEAR_ALL);

	/*  m_spRenderer->SetScreenSpaceCameraData();
    pkSplash->Draw(m_spRenderer);*/
  

	NiDrawScene(m_spCamera, m_spScene, kCuller);

}

void HiGBRenderer::EndScene()
{
	m_spRenderer->EndUsingRenderTargetGroup();
	m_spRenderer->EndFrame();
	m_spRenderer->DisplayFrame();
}


void HiGBRenderer::Terminate()
{
	m_gs_spWireframe = NULL;
}
//---------------------------------------------------------------------------
NiCamera* HiGBRenderer::FindCamera(NiAVObject* pkObject)
{
	// This function recursively walks the scenegraph until a camera
	// is found.

	if (NiIsKindOf(NiCamera, pkObject))
	{
		return (NiCamera*) pkObject;
	}
	else if (NiIsKindOf(NiNode, pkObject))
	{
		// NiNodes are the primary structural objects in Gamebryo. They 
		// group other Gamebryo scene objects together under a common parent
		// and coordinate system. NiNodes can have as many children as 
		// necessary, but those children are not guaranteed to be contiguous.

		NiNode* pkNode = (NiNode*) pkObject;
		for (unsigned int ui = 0; ui < pkNode->GetArrayCount(); ui++)
		{
			NiCamera* pkFoundCamera = FindCamera(pkNode->GetAt(ui));
			if (pkFoundCamera)
				return pkFoundCamera;
		}
	}

	return NULL;
}


NiAVObject* HiGBRenderer::GetObjectByName(char* name)
{
	return m_spScene->GetObjectByName(name);

}

bool HiGBRenderer::LoadCharacter(const char* filename)
{

	m_spActorManager = NiActorManager::Create(filename);

	m_spActorManager->Update(0.0f);
	//m_spActorManager->SetTargetAnimation(LM_Anim::IDLE01BASE);

	m_pkNode = (NiNode*) m_spActorManager->GetNIFRoot();
	m_pkNode->Update(0.0f);
	m_pkNode->UpdateProperties();
	m_pkNode->UpdateEffects();
	m_pkNode->SetScale(0.1f);

	m_pkNode->SetTranslate(0.0f,0.0f,0.0f);



	
	m_ScNode = NiNew NiSwitchNode;
	m_ScNode->AttachChild(m_pkNode);
	
	m_node->AttachChild(m_ScNode);

	NiMatrix3 kRotation = m_spActorManager->GetNIFRoot()->GetRotate();

	float fZ = -3937 * (1.0f / 127.0f);
	float fZRot =  NI_PI / 64.0f * fZ;
	NiMatrix3 kIncRototation;
	kIncRototation.MakeZRotation(fZRot);
	kRotation = kIncRototation * kRotation;

	m_ScNode->SetRotate(kRotation);

//	NiMatrix3 kRotation = m_pkNode->GetRotate();
//	float fRot = 1.57f;
//	NiMatrix3 kRotInc;
//	kRotInc.MakeZRotation(fRot);
//	m_pkNode->SetRotate(kRotation*kRotInc);

//	NiDirectionalLight* pkDirLight = NiNew NiDirectionalLight;
//	pkDirLight->SetAmbientColor(NiColor::BLACK);
//	pkDirLight->SetDiffuseColor(NiColor(0.7f, 0.7f, 0.85f));
//	pkDirLight->AttachAffectedNode(m_node);
//	m_node->AttachChild(pkDirLight);

//	NiSpecularProperty* m_spSpecular;
//	m_spSpecular = NiNew NiSpecularProperty;
//	m_node->AttachProperty(m_spSpecular);
//	m_spSpecular->SetSpecular(true);



	m_ScNode->SetIndex(0);

	return true;
}
NiNodePtr HiGBRenderer::LoadEffect(const char* filename)
{
	NiStream kStreamEffect;
	bool bSuccess = kStreamEffect.Load(filename);   
	m_pkEffect = (NiNode*) kStreamEffect.GetObjectAt(0);
	NIASSERT(NiIsKindOf(NiNode, m_pkEffect));
	m_pkEffect->SetTranslate(0.0f,0.0f,0.0f);

	return m_pkEffect;
}

//
//bool HiGBRenderer::Load(const char* filename)
//{
//	NiAlphaAccumulator* pkAccum = NiNew NiAlphaAccumulator;
//	m_spRenderer->SetSorter(pkAccum);
//
//	NiStream kStream;
//
//	// Load in the scenegraph for our world...
//	bool bSuccess = kStream.Load(filename);
//
//
//	if (!bSuccess)
//	{
//		NiMessageBox("WORLD.NIF file could not be loaded!", "NIF Error");
//		return false;
//	}
//
//	m_node = (NiNode*) kStream.GetObjectAt(0);
//	NIASSERT(NiIsKindOf(NiNode, m_node));
//
//	m_sNode = NiNew NiSwitchNode;
//	m_sNode->AttachChild(m_node);
//
//	m_spScene->AttachChild(m_sNode);
//
//	m_sNode -> SetIndex(0);
//
//	if (m_node)
//	{
//		NiCamera* cam = FindCamera(m_node);
//		if ( cam != NULL)
//			m_spCamera = cam;
//	}
//
//
//	if (!m_spCamera)
//	{
//		NiMessageBox("The NIF file has no camera!", "Camera Error");
//		return false;
//	}
//
//	//// connect the parts and do initial update
//	m_spScene->Update(0.0f);
//	m_spScene->UpdateProperties();
//	m_spScene->UpdateEffects();
//	m_spCamera->Update(0.0f);
//
//	return true;
//
//
//}


NiNodePtr HiGBRenderer::Load(const char* filename)
{
	NiAlphaAccumulator* pkAccum = NiNew NiAlphaAccumulator;
	m_spRenderer->SetSorter(pkAccum);

	NiStream kStream;

	// Load in the scenegraph for our world...
	bool bSuccess = kStream.Load(filename);


	if (!bSuccess)
	{
		NiMessageBox("WORLD.NIF file could not be loaded!", "NIF Error");
		return false;
	}

	m_node = (NiNode*) kStream.GetObjectAt(0);
	NIASSERT(NiIsKindOf(NiNode, m_node));

//	m_sNode = NiNew NiSwitchNode;
//	m_sNode->AttachChild(m_node);

//	m_spScene->AttachChild(m_node);

//	m_sNode -> SetIndex(0);

	if (m_node)
	{
		NiCamera* cam = FindCamera(m_node);
		if ( cam != NULL)
			m_spCamera = cam;
	}


	if (!m_spCamera)
	{
	NiMessageBox("The NIF file has no camera!", "Camera Error");
		return NULL;
	}

//	NiMatrix3 kRotation = m_node->GetRotate();
//	float fRot = 1.57f;
//	NiMatrix3 kRotInc;
//	kRotInc.MakeZRotation(fRot);
//	m_node->SetRotate(kRotation*kRotInc);
//
//	kRotation = m_node->GetRotate();
//	fRot = 1.57f;
//	kRotInc.MakeXRotation(fRot);
//	m_node->SetRotate(kRotation*kRotInc);



//	CreateAxisLines();

	//// connect the parts and do initial update
	m_spScene->Update(0.0f);
	m_spScene->UpdateProperties();
	m_spScene->UpdateEffects();
	m_spCamera->Update(0.0f);

	return m_node;


}



bool HiGBRenderer::CreateShaderSystem()
{
	// Register for an application callback should a shader fail to compile.
	NiShaderFactory::RegisterErrorCallback(ShaderCallback_Errors);

	// Set up the shader directories that we will use to parse.
	const char* pcShaderDir = "Shaders";
#if defined(_XENON)
	const char* pcShaderProgramDir = "Shaders\\Xenon";
#elif defined(WIN32)
	const char* pcShaderProgramDir = "Shaders\\D3D10";
#elif defined(_PS3)
	const char* pcShaderProgramDir = "Shaders/PS3";
#else
#error "Unknown platform"
#endif

	// Tell the shader factory where to locate any GPU program files.
	// These are files used by shaders such as vsh, psh, cg, or hlsl files.
	NiShaderFactory::AddShaderProgramFileDirectory(
		"../DATA/Shaders/Common");
	NiShaderFactory::AddShaderProgramFileDirectory(
		"../DATA/Shaders");

	// First, we will run the parsers. This is done to make sure that
	// any text-based shader files that have been modified are re-compiled
	// to binary before loading all the binary representations.
	if (!RunShaderParsers("../DATA/Shaders"))
	{
		NiMessageBox("Failed to run shader parsers!", "ERROR");
		return true;
	}

	// Run the shader libraries. This will load any shaders in the specified
	// data folder.
	if (!RunShaderLibraries("../DATA/Shaders"))
	{
		NiMessageBox("Failed to run shader parsers!", "ERROR");
		return true;
	}

	return true;
}
//---------------------------------------------------------------------------
bool HiGBRenderer::RunShaderParsers(const char* pcShaderDir)
{
	// Set up the callback defined for this application. If we were based on
	// DLL's we would not specify the callback function and we would use
	// the default callback instead.
	NiShaderFactory::RegisterRunParserCallback(ShaderCallback_RunParser);

	// Note that we do not need to specify the library name into 
	// LoadAndRunParserLibrary because we are only supporting one parser in
	// this application. If multiple parsers were to be supported, the 
	// callback would need to be called once per parser lib type, passing in
	// the parser lib name each time. Also note that in DLL builds, the  
	// pcLibName would specify the filename of the DLL to load that contained  
	// the shader parser.
	const char* pcLibName = NULL;

	// Tell the shader factory to parse all of the shaders in the specified
	// folder and all subfolders. In the process of parsing a file, the
	// ShaderCallback_RunParser method will be called. Parsing shader files
	// is done prior to loading the shader libraries because the parsers 
	// convert shader files into alternative formats without actually loading
	// the shaders into memory.
	NiShaderFactory::LoadAndRunParserLibrary(pcLibName, 
		pcShaderDir, true);
	return true;
}
//---------------------------------------------------------------------------
bool HiGBRenderer::RunShaderLibraries(const char* pcShaderDir)
{
	// Set up the callback defined for this application. If we were based on
	// DLL's we would not specify the callback function and we would use
	// the default callback instead.
	NiShaderFactory::RegisterClassCreationCallback(
		ShaderCallback_LibraryClassCreate);

	// Set up the directories to load. Note that more than one directory is
	// supported, although we only need to load from the Data/Shaders folder.
	unsigned int uiCount = 1;
	char* apcDirectories[1];
	apcDirectories[0] = (char*)(pcShaderDir);

	// Note that we do not need to specify the library name into 
	// LoadAndRegisterShaderLibrary because we are only supporting one library 
	// in this application. If multiple shader library were to be supported,  
	// the callback would need to be called once per lib type, passing in
	// the lib name each time. Also note that in DLL builds, the pcLibName 
	// would specify the filename of the DLL to load that contained the 
	// shader library.
	const char* pcLibName = NULL;

	// Tell the shader factory to load all of the shaders in the specified
	// folder and all subfolders. In the process of loading a file, the
	// ShaderCallback_LibraryClassCreate method will be called.
	if (!NiShaderFactory::LoadAndRegisterShaderLibrary(pcLibName, uiCount, 
		apcDirectories, true))
	{
		NiMessageBox("Failed to load shader library!", "ERROR");
		return false;
	}

	return true;
}
//---------------------------------------------------------------------------
bool HiGBRenderer::ShaderCallback_LibraryClassCreate(const char* pcLibFile, 
									   NiRenderer* pkRenderer, int iDirectoryCount, char* apcDirectories[], 
									   bool bRecurseSubFolders, NiShaderLibrary** ppkLibrary)
{
	// The library variable tells the shader factory to insert the shader
	// library into its list of known shader libraries. Set it to NULL
	// by default just in case the subsequent function call fails.
	*ppkLibrary = NULL;

	// Call the shader library loader on the specified directory.
	// Note that if multiple libraries were supported in this app, we would
	// need to compare against the pcLibFile.
	if (!NSBShaderLib_LoadShaderLibrary(pkRenderer, iDirectoryCount, 
		apcDirectories, bRecurseSubFolders, ppkLibrary))
	{
		return false;
	}

	return true;
}
//---------------------------------------------------------------------------
unsigned int HiGBRenderer::ShaderCallback_RunParser(const char* pcLibFile, 
									  NiRenderer* pkRenderer, const char* pcDirectory, 
									  bool bRecurseSubFolders)
{
	// Call the shader parser on the specified directory.
	// Note that if multiple parsers were supported in this app, we would
	// need to compare against the pcLibFile.
	return NSFParserLib_RunShaderParser(pcDirectory, bRecurseSubFolders);
//	return 1;
}
//---------------------------------------------------------------------------

unsigned int HiGBRenderer::ShaderCallback_Errors(const char* pcError, 
								   NiShaderError eError, bool bRecoverable)
{
	// Report any errors to the user
	NiOutputDebugString("ERROR: ");
	NiOutputDebugString(pcError);
	return 0;
}

// gamebryo new methods

NiScreenElements* HiGBRenderer::NewScreenElements()
{
	return NiNew NiScreenElements(
        NiNew NiScreenElementsData(false, false, 1));
}

NiTexturingProperty* HiGBRenderer::NewTexturingProperty()
{
	return NiNew NiTexturingProperty(
        "Splash.dds");
}

NiSourceTexture* HiGBRenderer::NewSourceTexture(const NiFixedString& kFilename)
{
	return NiSourceTexture::Create(kFilename);
}

NiScreenTexture* HiGBRenderer::NewScreenTexture(NiSourceTexture* pkSourceTexture)
{
	return  NiNew NiScreenTexture(pkSourceTexture);
}


NiFont* HiGBRenderer::NewFontCreate(NiRenderer* pkRenderer, const char* pcFontFile)
{
	return NiFont::Create(pkRenderer,pcFontFile);
}
NiOldString2D* HiGBRenderer::NewFont(NiFont* pkFont, unsigned int uiFlags,
									unsigned int uiMaxStringLen, const char* pcString,
									const NiColorA& kColor, unsigned int uiX, unsigned int uiY)
{
	return NiNew NiOldString2D(pkFont, uiFlags, uiMaxStringLen,	pcString, kColor, uiX, uiY);
}
NiDI8InputSystem::DI8CreateParams* HiGBRenderer::NewInputSystem()
{
	return NiNew NiDI8InputSystem::DI8CreateParams();
}
NiInputSystem* HiGBRenderer::NewInputCreate(NiInputSystem::CreateParams* pkParams)
{
	return NiInputSystem::Create(pkParams);
}
NiActorManager* HiGBRenderer::NewCharacterCreate(const char* filename)
{
	return NiActorManager::Create(filename);

}
NiDirectionalLight* HiGBRenderer::NewNiDirectionalLight()
{
	return NiNew NiDirectionalLight;
}
NiNode* HiGBRenderer::NewNiNode()
{
	return NiNew NiNode;
}

bool HiGBRenderer::CreateInputSystem(HWND hWnd, HINSTANCE hInst)
{
	// Create and initialize parameters for the input system
	NiInputSystem::CreateParams* pkParams = GetInputSystemCreateParams( hWnd, hInst);

	// Create the input system
	m_spInputSystem = NiInputSystem::Create(pkParams);
	NiDelete pkParams;
	if (!m_spInputSystem)
	{
		NiMessageBox("CreateInputSystem: Creation failed.", 
			"NiApplication Error");
		return false;
	}

	// The creation of the input system automatically starts an enumeration
	// of the devices. 
	NiInputErr eErr = m_spInputSystem->CheckEnumerationStatus();
	switch (eErr)
	{
	case NIIERR_ENUM_NOTRUNNING:
		NIASSERT(!"EnumerateDevices failed?");
		return false;
	case NIIERR_ENUM_FAILED:
		NIASSERT(!"CheckEnumerationStatus> FAILED!");
		return false;
	case NIIERR_ENUM_COMPLETE:
	case NIIERR_ENUM_NOTCOMPLETE:
	default:
		break;
	}

	// On Win32, assume there is a mouse and keyboard
	if (!m_spInputSystem->OpenMouse() || !m_spInputSystem->OpenKeyboard())
	{
		NiMessageBox("CreateInputSystem: Mouse or keyboard failed to open.", 
			"NiApplication Error");
		return false;
	}

	// Gamepad may not exist, but attempt to open any
	for (unsigned int iGamePad = 0; 
		iGamePad < NiInputSystem::MAX_GAMEPADS;
		iGamePad++
		)
	{
		m_spInputSystem->OpenGamePad(iGamePad,0);
	}

	return true;
}
NiInputSystem::CreateParams* HiGBRenderer::GetInputSystemCreateParams(HWND hWnd, HINSTANCE hInst)
{
	NiDI8InputSystem::DI8CreateParams* pkParams = 
		NiNew NiDI8InputSystem::DI8CreateParams();
	NIASSERT(pkParams);

	pkParams->SetRenderer(m_spRenderer);
	pkParams->SetKeyboardUsage(
		NiInputSystem::FOREGROUND | NiInputSystem::NONEXCLUSIVE);

	unsigned int uiMouseFlags = NiInputSystem::FOREGROUND;
//	if (m_bExclusiveMouse)
//	{
//		uiMouseFlags |= NiInputSystem::EXCLUSIVE;
//	}
//	else
//	{
		uiMouseFlags |= NiInputSystem::NONEXCLUSIVE;
//	}

	pkParams->SetMouseUsage(uiMouseFlags);
	pkParams->SetGamePadCount(2);
	pkParams->SetAxisRange(-100, +100);
	pkParams->SetOwnerInstance(hInst);
	pkParams->SetOwnerWindow(hWnd);

	return pkParams;
}
NiInputSystem* HiGBRenderer::GetInputSystem()
{
	return m_spInputSystem;
}
NiAlphaAccumulator* HiGBRenderer::NewAlphaAccumulator()//;//pkAccum = NiNew NiAlphaAccumulator;
{
	return NiNew NiAlphaAccumulator;
}

